﻿using SqlSugar;

namespace FastCodeGeneration.Core.Framework
{
    public class QueryWrapper<T>
    {
        private const string AND = "and";

        private const string OR = "or";

        private List<string> parameters = new List<string>();

        private List<SugarParameter> sugarParameters = new List<SugarParameter>();

        private int parameterIndex = 0;

        private bool use_or = false;

        public QueryWrapper() { }
        public QueryWrapper(int parameterIndex)
        {
            this.parameterIndex = parameterIndex;
        }

        /// <summary>
        /// 获取查询参数
        /// </summary>
        /// <returns></returns>
        public List<SugarParameter> GetSugarParameters() { return sugarParameters; }

        /// <summary>
        /// 获取生成的sql结果
        /// </summary>
        /// <returns></returns>
        public string getSqlResult()
        {
            return "(" + string.Join(" ", parameters) + ")";
        }
        /// <summary>
        /// 参数下标
        /// </summary>
        public int ParameterIndex
        {
            get
            {
                return parameterIndex;
            }
        }
        /// <summary>
        /// 获取一个占位符
        /// </summary>
        /// <returns></returns>
        private string getPlaceholder()
        {
            return "@parameter" + parameterIndex++;
        }
        /// <summary>
        /// 使用or连接
        /// </summary>
        /// <returns></returns>
        public QueryWrapper<T> or()
        {
            use_or = true;
            var sql = getSqlResult();
            parameters.Clear();
            parameters.Add(sql);
            parameters.Add(OR);
            return this;
        }

        public QueryWrapper<T> or(Action<QueryWrapper<T>> action)
        {
            var wrapper = new QueryWrapper<T>(parameterIndex);
            if (action != null)
            {
                action(wrapper);
            }
            if (parameters.Count > 0)
            {
                parameters.Add(OR);
            }
            parameters.Add(wrapper.getSqlResult());
            sugarParameters.AddRange(wrapper.GetSugarParameters());
            parameterIndex = wrapper.ParameterIndex;
            return this;
        }

        public QueryWrapper<T> and(Action<QueryWrapper<T>> action)
        {
            var wrapper = new QueryWrapper<T>(parameterIndex);
            if (action != null)
            {
                action(wrapper);
            }
            if (parameters.Count > 0)
            {
                parameters.Add(AND);
            }
            parameters.Add(wrapper.getSqlResult());
            sugarParameters.AddRange(wrapper.GetSugarParameters());
            parameterIndex = wrapper.ParameterIndex;
            return this;
        }




        /// <summary>
        /// 设置查询参数
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="connector">条件连接符</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> Build(string field, string connector, object value)
        {
            return Build(field, connector, value, getPlaceholder());
        }
        /// <summary>
        /// 设置查询参数
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="connector">条件连接符</param>
        /// <param name="value">值</param>
        /// <param name="placeholder">占位符</param>
        /// <returns></returns>
        public QueryWrapper<T> Build(string field, string connector, object value, string placeholder)
        {
            if (parameters.Count > 0)
            {
                if (use_or)
                    parameters.Add(OR);
                else
                    parameters.Add(AND);

            }
            var param = $"{field} {connector} {placeholder}";
            parameters.Add(param);
            sugarParameters.Add(new SugarParameter(placeholder, value));
            return this;
        }

        /// <summary>
        /// 等于
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> Eq(string field, object value)
        {
            return Build(field, "=", value);
        }


        /// <summary>
        /// 不等于
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> Ne(string field, object value)
        {
            return Build(field, "!=", value);
        }

        /// <summary>
        /// 大于
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> Gt(string field, object value)
        {
            return Build(field, ">", value);
        }


        /// <summary>
        /// 大于等于
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> Ge(string field, object value)
        {
            return Build(field, ">=", value);
        }

        /// <summary>
        /// 小于
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> Lt(string field, object value)
        {
            return Build(field, "<", value);
        }

        /// <summary>
        /// 小于等于
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> Le(string field, object value)
        {
            return Build(field, "<=", value);
        }


        /// <summary>
        /// in
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> In(string field, params object[] value)
        {
            return Build(field, "in", value, "(" + getPlaceholder() + ")");
        }

        /// <summary>
        /// not in
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> NotIn(string field, params object[] value)
        {
            return Build(field, "not in", value, "(" + getPlaceholder() + ")");
        }

        /// <summary>
        /// like
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public QueryWrapper<T> Like(string field, string value)
        {
            return Build(field, "like", "%" + value + "%");
        }

    }
}
